package com.middleware.mappers;

import com.middleware.utils.CommonUtil;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class ExecutorResultMapper {

    public static <T> T map(ResultSet resultSet, Class<T> clazz, Type genericReturnType) throws SQLException {
        //如果是 list 类型的返回值
        if(List.class.isAssignableFrom(clazz)){
            return (T) mapResultSetToList(resultSet, getActualType(genericReturnType));
        }else{
            return mapResultSetToObject(resultSet, clazz);
        }
    }

    /**
     * 将ResultSet映射为单个对象
     */
    @SuppressWarnings("unchecked")
    private static <T> T mapResultSetToObject(ResultSet rs, Class<T> clazz) throws SQLException {
        if (!rs.next()) {
            // 根据返回类型决定返回null还是空对象
            if (clazz.isPrimitive()) {
                return CommonUtil.getPrimitiveDefaultValue(clazz);
            }
            return null;
        }

        try {
            // 基本类型直接返回
            if (clazz.isPrimitive() || CommonUtil.isWrapperType(clazz) || clazz.equals(String.class)) {
                Object value = rs.getObject(1);
                return (T) (value != null ? value : CommonUtil.getPrimitiveDefaultValue(clazz));
            }

            // 创建对象实例
            T obj = clazz.getDeclaredConstructor().newInstance();
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 遍历所有列
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnLabel(i);
                Object value = rs.getObject(i);

                // 设置对象属性值
                setProperty(obj, columnName, value);
            }
            return obj;
        } catch (Exception e) {
            throw new RuntimeException("结果集映射失败: " + e.getMessage(), e);
        }
    }

    /**
     * 将ResultSet映射为List
     */
    private static <T> List<T> mapResultSetToList(ResultSet rs, Class<T> elementType) throws SQLException {
        List<T> list = new ArrayList<>();

        while (rs.next()) {
            try {
                if (elementType.isPrimitive() || CommonUtil.isWrapperType(elementType) || elementType.equals(String.class)) {
                    // 基本类型列表
                    Object value = rs.getObject(1);
                    list.add(elementType.cast(value != null ? value : CommonUtil.getPrimitiveDefaultValue(elementType)));
                } else {
                    // 对象类型列表
                    T obj = elementType.getDeclaredConstructor().newInstance();
                    ResultSetMetaData metaData = rs.getMetaData();
                    int columnCount = metaData.getColumnCount();

                    for (int i = 1; i <= columnCount; i++) {
                        String columnName = metaData.getColumnLabel(i);
                        Object value = rs.getObject(i);
                        setProperty(obj, columnName, value);
                    }
                    list.add(obj);
                }
            } catch (Exception e) {
                throw new RuntimeException("结果集映射失败", e);
            }
        }
        return list;
    }

    /**
     * 通过反射设置对象属性值
     */
    private static void setProperty(Object obj, String columnName, Object value) {
        try {
            // 下划线转驼峰：user_name -> userName[7](@ref)
            String propertyName = CommonUtil.toCamelCase(columnName);
            java.lang.reflect.Field field = getAccessibleField(obj.getClass(), propertyName);

            if (field != null && value != null) {
                // 类型转换
                Object convertedValue = CommonUtil.convertType(value, field.getType());
                field.set(obj, convertedValue);
            }
        } catch (Exception e) {
            // 忽略设置失败的属性（可能是没有对应字段）
            e.printStackTrace();
        }
    }

    /**
     * 获取可访问的字段（包括父类）
     */
    private static java.lang.reflect.Field getAccessibleField(Class<?> clazz, String fieldName) {
        Class<?> currentClass = clazz;
        while (currentClass != null) {
            try {
                java.lang.reflect.Field field = currentClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            } catch (NoSuchFieldException e) {
                currentClass = currentClass.getSuperclass();
            }
        }
        return null;
    }

    private static Class<?> getActualType(java.lang.reflect.Type genericType) {
        //检查一下是否是泛型参数
        if (genericType instanceof java.lang.reflect.ParameterizedType) {
            java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) genericType;
            return (Class<?>) pt.getActualTypeArguments()[0];
        }
        return Object.class;
    }

}
